package com.maigao.service;

import com.maigao.entity.form.AddStudentForm;
import com.maigao.entity.form.SearchStudentForm;
import com.maigao.entity.jpa.Coach;
import com.maigao.entity.jpa.QueryStudentCourse;
import com.maigao.entity.jpa.Student;
import com.maigao.entity.jpa.User;
import com.maigao.entity.vo.NewlyAddedStudentVo;
import com.maigao.entity.vo.StudentVO;
import com.maigao.persistent.CoachRepository;
import com.maigao.persistent.StudentRepository;
import com.maigao.persistent.UserRepository;
import com.maigao.util.CollectionUtils;
import com.maigao.util.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @program: maigao
 * @description:
 * @author: yongza
 * @create: 2024-10-21 23:01
 **/
@Service
public class StudentService {
    @Autowired
    private StudentRepository studentRepository;
    @Autowired
    private CoachRepository coachRepository;
    @Autowired
    private UserService userService;
    @Autowired
    private UserRepository userRepository;

    public List<StudentVO> tryFindAll() {
        List<Student> students = studentRepository.findAll();

        return convert2Detail(students);
    }

    public List<StudentVO> convert2Detail(List<Student> students) {
        List<StudentVO> studentVOS = new ArrayList<>();
        for (Student student : students) {
            StudentVO studentVO = new StudentVO();
            BeanUtils.copyProperties(student, studentVO);
            studentVO.setCreateTime(DateUtils.format(student.getCreateTime(), DateUtils.Formatter.DATETIME_YYYY_MM_DD_HH_MM_SS));
            studentVOS.add(studentVO);
        }
        return studentVOS;
    }

    public Triple<Boolean, StudentVO, String> tryFindStudent(SearchStudentForm searchStudentForm) {
        Integer studentId = searchStudentForm.getStudentId();
        String studentName = searchStudentForm.getStudentName();
        String userUid = searchStudentForm.getUserUid();
        if (StringUtils.isAnyBlank(studentName, userUid) && null == studentId) {
            return Triple.of(false, null, "参数有误!");
        }
        Student student;
        if (null != studentId) {
            student = studentRepository.findById(studentId);
        } else {
            student = studentRepository.findByUserUidAndStudentName(userUid, studentName);
        }
        if (null == student) {
            return Triple.of(false, null, "未查询到相关数据!");
        }
        StudentVO studentVO = new StudentVO();
        BeanUtils.copyProperties(student, studentVO);
        return Triple.of(true, studentVO, "");
    }

    public Triple<Boolean, List<StudentVO>, String> trySearchStudent(String userName) {
        if (StringUtils.isBlank(userName)) {
            return Triple.of(false, null, "参数有误!");
        }
        List<Student> students = studentRepository.findByStudentNameLikeAndStatus(userName, Student.Status.NORMAL.getValue());
        if (CollectionUtils.isEmpty(students)) {
            return Triple.of(false, null, "未查询到相关数据!");
        }

        return Triple.of(true, convert2Detail(students), "");
    }

    public Triple<Boolean, String, StudentVO> tryAddStudent(AddStudentForm addStudentForm) {
        String mobile = addStudentForm.getMobile();
        String studentName = addStudentForm.getStudentName();
        Integer coachId = addStudentForm.getCoachId();
        String coachName = addStudentForm.getCoachName();
        if (StringUtils.isAnyBlank(coachName, mobile, studentName) || null == coachId) {
            return Triple.of(false, "参数不完整!", null);
        }
        Coach coach = coachRepository.findById(coachId);
        if (null == coach) {
            return Triple.of(false, "教练不存在!", null);
        }
        if (!StringUtils.equals(coach.getCoachName(), coachName)) {
            return Triple.of(false, "教练姓名错误!", null);
        }
        User user = userService.findUserByMobile(mobile);
        String userUid;
        String registrationCode;
        if (null == user) {
            user = userService.initUser();
            user.setUserName(studentName);
            user.setMobile(mobile);
            int userType = User.UserType.NORMAL.getValue();
            user.setUserType(userType);
            registrationCode = userService.createRegistrationCode(studentName, mobile, userType);
            user.setRegistrationCode(registrationCode);
            userRepository.save(user);

        } else {
            registrationCode = user.getRegistrationCode();
        }
        userUid = user.getUid();
        Student oldStudent = studentRepository.findByUserUidAndStudentName(userUid, studentName);
        if (null != oldStudent) {
            return Triple.of(false, "学生已存在!", null);
        }
        Student student = new Student();
        student.setStudentName(studentName);
        student.setUserUid(userUid);
        student.setCoachId(coachId);
        student.setCoachName(coachName);
        student.setCreateTime(LocalDateTime.now());
        student.setStatus(Student.Status.NORMAL.getValue());
        studentRepository.save(student);
        StudentVO studentVO = new StudentVO();
        BeanUtils.copyProperties(student, studentVO);
        studentVO.setRegistrationCode(registrationCode);
        return Triple.of(true, "", studentVO);
    }

    public Triple<Boolean, String, NewlyAddedStudentVo> findStudentByTimeRange(String fromTime, String endTime) {
        LocalDate fromDate = DateUtils.parseDate(fromTime, DateUtils.Formatter.DATE_YYYY_MM_DD);
        LocalDate endDate = DateUtils.parseDate(endTime, DateUtils.Formatter.DATE_YYYY_MM_DD);
        LocalDateTime fromDateTime = LocalDateTime.of(fromDate, LocalTime.MIN);
        LocalDateTime endDateTime = LocalDateTime.of(endDate, LocalTime.MAX);
        List<Student> students = studentRepository.findByCreateTimeBetween(fromDateTime, endDateTime);
        if (CollectionUtils.isEmpty(students)) {
            return Triple.of(false, "暂无新增学员!", null);
        }
        NewlyAddedStudentVo studentVo = new NewlyAddedStudentVo();
        studentVo.setCount(students.size());
        AtomicInteger totalSchoolFee = new AtomicInteger(0);
        students.forEach(x -> {
            Optional.ofNullable(x.getStudentCourses()).ifPresent(y -> {
                BigDecimal reduce = y.stream().map(QueryStudentCourse::getTotalPrice)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                totalSchoolFee.set(reduce.intValue());
            });
        });
        studentVo.setTotalSchoolFee(totalSchoolFee.get());
        studentVo.setStudentNames(students.stream().map(Student::getStudentName).collect(Collectors.toList()));
        return Triple.of(true, "", studentVo);
    }

    public Pair<Boolean, String> tryUpdateCoach(Integer studentId, Integer coachId) {
        Coach coach = coachRepository.findById(coachId);
        if (null == coach) {
            return Pair.of(false, "教练不存在!");
        }
        Student student = studentRepository.findById(studentId);
        if (null == student) {
            return Pair.of(false, "学生不存在!");
        }
        student.setCoachId(coach.getId());
        student.setCoachName(coach.getCoachName());
        studentRepository.save(student);
        return Pair.of(true, "");
    }

    public Pair<Boolean, String> tryUpdateStatus(Integer studentId, Integer newStatus) {
        Student student = studentRepository.findById(studentId);
        if (null == student) {
            return Pair.of(false, "学生不存在!");
        }
        Student.Status statusEnum = Student.Status.getByValue(newStatus);
        if (null == statusEnum) {
            return Pair.of(false, "状态非法!");
        }
        studentRepository.updateStudentStatus(studentId, newStatus);
        return Pair.of(true, "");
    }
}
